# network_client.py - 五子棋网络客户端模块

import socket
import threading
import json
import time

class NetworkClient:
    def __init__(self):
        self.client_socket = None
        self.connected = False
        self.username = None
        self.receive_thread = None
        self.callbacks = {
            "on_connect": None,
            "on_disconnect": None,
            "on_match_found": None,
            "on_move": None,
            "on_chat": None,
            "on_game_over": None,
            "on_waiting": None,
            "on_error": None,
            "on_undo_request": None,
            "on_undo_response": None,
            "on_timeout": None,
            "on_undo_update": None,
            "on_rematch_request": None,
            "on_rematch_response": None,
            "on_opponent_info": None
        }
    
    def connect(self, username, host="localhost", port=5000):
        """连接到服务器"""
        # 首先确保断开之前的连接
        self.disconnect()
        
        try:
            # 创建新的socket连接
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.connect((host, port))
            self.connected = True
            self.username = username
            
            # 发送登录消息
            login_success = self.send_message({
                "type": "login",
                "username": username
            })
            
            if not login_success:
                print("登录消息发送失败")
                self.disconnect()
                return False
            
            # 启动接收线程
            self.receive_thread = threading.Thread(target=self.receive_messages)
            self.receive_thread.daemon = True
            self.receive_thread.start()
            
            if self.callbacks["on_connect"]:
                self.callbacks["on_connect"]()
            
            print(f"成功连接到服务器：{host}:{port}，用户名：{username}")
            return True
        except Exception as e:
            print(f"连接失败: {e}")
            self.connected = False
            if self.callbacks["on_error"]:
                self.callbacks["on_error"](f"连接失败: {e}")
            # 确保清理资源
            if self.client_socket:
                try:
                    self.client_socket.close()
                except:
                    pass
                self.client_socket = None
            return False
    
    def disconnect(self):
        """断开连接"""
        # 无论是否连接，都尝试清理资源
        try:
            # 先标记为已断开连接，避免重复处理
            was_connected = self.connected
            self.connected = False
            
            # 关闭socket
            if self.client_socket:
                try:
                    self.client_socket.close()
                except Exception as e:
                    print(f"关闭socket时出错: {e}")
                self.client_socket = None  # 清空socket引用
            
            # 只有之前是连接状态才调用回调函数
            if was_connected and self.callbacks["on_disconnect"]:
                self.callbacks["on_disconnect"]()
        except Exception as e:
            print(f"断开连接时出错: {e}")
    
    def send_message(self, message):
        """发送消息到服务器"""
        if not self.connected:
            return False
        
        try:
            # 将消息转换为JSON字符串
            message_json = json.dumps(message)
            # 直接发送JSON字符串，不添加长度前缀
            self.client_socket.sendall(message_json.encode('utf-8'))
            return True
        except Exception as e:
            print(f"发送消息失败: {e}")
            self.connected = False
            if self.callbacks["on_disconnect"]:
                self.callbacks["on_disconnect"]()
            return False
    
    def receive_messages(self):
        """接收服务器消息的线程"""
        try:
            buffer = ""
            while self.connected:
                # 接收数据
                data = self.client_socket.recv(4096)
                if not data:
                    break
                
                # 将接收到的数据添加到缓冲区
                buffer += data.decode('utf-8')
                
                # 处理缓冲区中的所有完整JSON消息
                while True:
                    try:
                        # 尝试解析一个JSON对象
                        message, index = json.JSONDecoder().raw_decode(buffer)
                        # 处理消息
                        self.handle_message(message)
                        # 从缓冲区中移除已处理的消息
                        buffer = buffer[index:].strip()
                        if not buffer:
                            break
                    except json.JSONDecodeError:
                        # 如果不是完整的JSON，等待更多数据
                        break
                
        except Exception as e:
            print(f"接收消息时出错: {e}")
        finally:
            self.connected = False
            if self.callbacks["on_disconnect"]:
                self.callbacks["on_disconnect"]()
    
    def handle_message(self, message):
        """处理接收到的消息"""
        message_type = message.get("type")
        
        if message_type == "login_response":
            # 登录响应
            status = message.get("status", "")
            if status == "success":
                if self.callbacks["on_connect"]:
                    self.callbacks["on_connect"]()
            else:
                error = message.get("message", "登录失败")
                if self.callbacks["on_error"]:
                    self.callbacks["on_error"](error)
        
        elif message_type == "waiting_match":
            # 等待匹配
            if self.callbacks["on_waiting"]:
                self.callbacks["on_waiting"](message)
        
        elif message_type == "match_found":
            # 匹配成功
            if self.callbacks["on_match_found"]:
                self.callbacks["on_match_found"](message)
        
        elif message_type == "game_start":
            # 游戏开始
            if self.callbacks["on_match_found"]:
                self.callbacks["on_match_found"](message)
        
        elif message_type == "move_response":
            # 落子响应
            if self.callbacks["on_move"]:
                self.callbacks["on_move"](message)
        
        elif message_type == "chat_message":
            # 聊天消息
            if self.callbacks["on_chat"]:
                self.callbacks["on_chat"](message)
        
        elif message_type == "game_over":
            # 游戏结束
            if self.callbacks["on_game_over"]:
                self.callbacks["on_game_over"](message)
        
        elif message_type == "opponent_info":
            # 对手信息，用于更新排行榜
            print(f"收到对手信息: {message}")
            if self.callbacks.get("on_opponent_info"):
                self.callbacks["on_opponent_info"](message)
        
        elif message_type == "opponent_disconnected":
            # 对手断开连接
            print(f"收到对手断开连接消息: {message}")
            if self.callbacks["on_game_over"]:
                # 将对手断开连接视为游戏结束
                game_over_data = {
                    "type": "game_over",
                    "reason": "opponent_disconnected",
                    "winner": message.get("winner", "you"),  # 使用服务器提供的获胜者信息
                    "message": message.get("message", "对手已断开连接"),
                    "has_moves": True  # 确保显示断开连接的对话框
                }
                print(f"转发为游戏结束消息: {game_over_data}")
                self.callbacks["on_game_over"](game_over_data)
        
        elif message_type == "error":
            # 错误消息
            if self.callbacks["on_error"]:
                self.callbacks["on_error"](message.get("message", "未知错误"))
        
        elif message_type == "undo_request":
            # 悔棋请求
            if self.callbacks["on_undo_request"]:
                self.callbacks["on_undo_request"](message)
        
        elif message_type == "undo_response":
            # 悔棋回应
            if self.callbacks["on_undo_response"]:
                self.callbacks["on_undo_response"](message)
        
        elif message_type == "timeout":
            # 超时消息
            if self.callbacks["on_timeout"]:
                self.callbacks["on_timeout"](message)
        
        elif message_type == "undo_update":
            # 悔棋更新
            if self.callbacks["on_undo_update"]:
                self.callbacks["on_undo_update"](message)
                
        elif message_type == "rematch_request":
            # 重新比赛请求
            print(f"收到重新比赛请求消息: {message}")
            if self.callbacks["on_rematch_request"]:
                self.callbacks["on_rematch_request"](message)
                
        elif message_type == "rematch_response":
            # 重新比赛回应
            if self.callbacks["on_rematch_response"]:
                self.callbacks["on_rematch_response"](message)
    
    def find_game(self):
        """寻找对局"""
        return self.send_message({
            "type": "find_game"
        })
    
    def make_move(self, x, y):
        """落子"""
        return self.send_message({
            "type": "move",
            "x": x,
            "y": y
        })
    
    def send_chat(self, content):
        """发送聊天消息"""
        return self.send_message({
            "type": "chat",
            "content": content
        })
    
    def surrender(self):
        """投降"""
        return self.send_message({
            "type": "surrender"
        })
        
    
    def request_undo(self):
        """请求悔棋"""
        return self.send_message({
            "type": "undo_request"
        })
    
    def respond_to_undo(self, allowed):
        """回应悔棋请求"""
        return self.send_message({
            "type": "undo_response",
            "allowed": allowed
        })
    
    def set_callback(self, event, callback):
        """设置回调函数"""
        if event in self.callbacks:
            self.callbacks[event] = callback
            
    def request_rematch(self):
        """请求重新比赛"""
        print(f"请求重新比赛")
        return self.send_message({
            "type": "rematch_request"
        })
        
    def respond_to_rematch(self, allowed):
        """回应重新比赛请求"""
        return self.send_message({
            "type": "rematch_response",
            "allowed": allowed
        })